<template>
  <div v-if = "isshow">
    params
  </div>
  <div v-else>
    <self-breadcrumb :bread-arr = "['商品管理','分类参数']"></self-breadcrumb>
    <el-card class = "box-card">
      <div slot = "header" class = "clearfix">
        <el-alert
            title = "注意：只允许为第三级分类设置相关参数"
            show-icon
            :closable = "false"
            style = "margin-bottom: 20px;"
            type = "warning">
        </el-alert>
        <el-cascader
            clearable
            style = "width: 50%"
            v-model = "selectCategories"
            :options = "categoriesList"
            ref = "paramsCascader"
            :props = "{ expandTrigger: 'hover',value:'cat_id',label:'cat_name' }"
            @change = "handleChange"></el-cascader>
      </div>
      <template>
        <!--
          tabs标签页，使用el-tab-pane来指定多个标签页，标签页可以与动态绑定一个参数，该参数为当前激活的标签页的name属性
          所以我们可以给标签页不同的name值，并且可以取到
        -->
        <el-tabs v-model = "activeName" @tab-click = "tabClick">
          <el-tab-pane label = "动态参数" name = "many">
            <template>
              <el-button
                  :disabled = "selectCategories.length!==3"
                  @click = "addDialogVisible = true"
                  type = "primary">添加参数
              </el-button>
              <el-table
                  :data = "manyTabData"
                  border
                  style = "width: 100%">
                <el-table-column
                    type = "expand">
                  <template slot-scope = "scope">
                    <el-tag @close = "tagClose(scope.row,index)"
                            closable
                            v-for = "(item,index) in scope.row.attr_vals"
                            :key = "index"
                            v-show = "item.length!==0">
                      {{item}}
                    </el-tag>
                    <!--
                    这里比较巧妙， 也就是new tag 添加tag标签的实现，使用了一个input和一个tag，
                    当我们点击tag时tag就隐藏，input就出现并获得焦点，当input失去焦点或键入回车(回车也会导致失去焦点)时，
                    就执行操作添加新标签，然后再次让input隐藏，tag显示，就可以不断的添加新标签了。
                    因为有些分类有多个参数和属性，如果我们都绑定一个控制显示的参数，或者都双向绑定一个值的话，那么就会出现
                    问题，比如我点击一个添加新属性，那么其他的属性也会出现input框，并且输入的内容都是双向绑定的
                    所以我们需要给每一个参数或者属性对象添加控制显示的属性和值。 但是添加属性一定要在请求到数据之后就添加
                    如果在已经赋给了data中的值后再添加，就会出现并不能双向绑定的问题。
                    -->
                    <el-input
                        class = "input-new-tag"
                        v-if = "scope.row.newTagInputVisible"
                        v-model = "scope.row.newTagValue"
                        @blur = "newTagInputBlur(scope.row)"
                        @keydown.enter.native = "newTagInputBlur(scope.row)"
                        ref = "newTagInputRef"
                        size = "small">
                    </el-input>
                    <el-button
                        v-else
                        class = "button-new-tag"
                        size = "small"
                        @click = "showNewTagInput(scope.row)">
                      + New Tag
                    </el-button>
                    {{scope.row}}
                  </template>
                </el-table-column>
                <el-table-column
                    type = "index"
                    label = "#">
                </el-table-column>
                <el-table-column
                    prop = "attr_name"
                    label = "参数名称">
                </el-table-column>
                <el-table-column
                    label = "操作">
                  <template slot-scope = "scope">
                    <el-button @click = "editParamsDataButton(scope.row)" size = "small"
                               type = "primary"
                               icon = "el-icon-edit">编辑
                    </el-button>
                    <el-button
                        @click = "deleteParamsDataButton(scope.row)"
                        size = "small" type = "danger"
                        icon = "el-icon-delete">
                      删除
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
            </template>
          </el-tab-pane>
          <el-tab-pane label = "静态属性" name = "only">
            <el-button
                type = "primary"
                :disabled = "selectCategories.length!==3"
                @click = "addDialogVisible=true">添加属性
            </el-button>
            <el-table
                border
                :data = "onlyTabData"
                style = "width: 100%">
              <el-table-column
                  type = "expand">
                <template slot-scope = "scope">
                  <el-tag @close = "tagClose(scope.row,index)"
                          closable
                          v-for = "(item,index) in scope.row.attr_vals"
                          :key = "index"
                          v-show = "item.length!==0"
                          type = "success">
                    {{item}}
                  </el-tag>
                  <el-input
                      class = "input-new-tag"
                      v-if = "scope.row.newTagInputVisible"
                      v-model = "scope.row.newTagValue"
                      @blur = "newTagInputBlur(scope.row)"
                      @keydown.enter.native = "newTagInputBlur(scope.row)"
                      ref = "newTagInputRef"
                      size = "small">
                  </el-input>
                  <!--
                  点击按钮时，让输入框出现，按钮隐藏，并且让输入框获得焦点，要让输入框获得焦点，要让输入框获得焦点，
                  要使用原生的输入框方法，所以我们需要取得原生的输入框
                   -->
                  <el-button
                      v-else
                      class = "button-new-tag"
                      size = "small"
                      @click = "showNewTagInput(scope.row)">
                    + New Tag
                  </el-button>
                </template>
              </el-table-column>
              <el-table-column
                  type = "index"
                  label = "#">
              </el-table-column>
              <el-table-column
                  prop = "attr_name"
                  label = "属性名称">
              </el-table-column>
              <el-table-column
                  label = "操作">
                <template slot-scope = "scope">
                  <el-button
                      size = "small"
                      type = "primary"
                      @click = "editParamsDataButton(scope.row)"
                      icon = "el-icon-edit">
                    编辑
                  </el-button>
                  <el-button @click = "deleteParamsDataButton(scope.row)" size = "small"
                             type = "danger"
                             icon = "el-icon-delete">
                    删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </el-tab-pane>
        </el-tabs>
      </template>
    </el-card>
    <el-dialog
        :title = "'添加'+titleText"
        :visible.sync = "addDialogVisible"
        @close = "addDialogClose"
        width = "50%">
      <el-form ref = "addFormRef" :rules = "addFormRules" :model = "addForm" label-width = "80px">
        <el-form-item :label = "titleText" prop = "attr_name">
          <el-input v-model = "addForm.attr_name" clearable></el-input>
        </el-form-item>
      </el-form>
      <span slot = "footer" class = "dialog-footer">
        <el-button @click = "addDialogVisible = false">取 消</el-button>
        <el-button type = "primary" @click = "addDialogDefine">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog
        :title = "'修改'+titleText"
        :visible.sync = "editDialogVisible"
        width = "50%">
      <el-form ref = "editFormRef" :model = "editForm" :rules = "addFormRules" label-width = "80px">
        <el-form-item :label = "titleText" prop = "attr_name">
          <el-input v-model = "editForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot = "footer" class = "dialog-footer">
        <el-button @click = "editDialogVisible = false">取 消</el-button>
        <el-button type = "primary" @click = "editParamsDataDefine">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import SelfBreadcrumb from '../SelfBreadcrumb'

export default {
  name: 'Params',
  components: {
    SelfBreadcrumb
  },
  created () {
    this.getCategoriesList()
  },
  data () {
    return {
      isshow: false,
      categoriesList: [],
      selectCategories: [],
      activeName: 'many',
      // 动态参数的数据
      manyTabData: [],
      // 静态属性的数据
      onlyTabData: [],
      // 控制 添加动态参数或静态属性对话框是否可见
      addDialogVisible: false,
      addForm: {
        attr_name: ''
      },
      addFormRules: {
        attr_name: [{ required: true, message: '不能为空', trigger: 'blur' }]
      },
      editDialogVisible: false,
      editAttrId: 0,
      editForm: {
        attr_name: ''
      }
    }
  },
  methods: {
    async getCategoriesList () {
      const { data: res } = await this.$http.get('categories')
      this.process(res)
      this.categoriesList = res.data
      console.log(this.categoriesList)
    },
    process (res) {
      const status = res.meta.status
      const msg = res.meta.msg
      if (status === 200 || status === 201 || status === 204) this.$message.success(msg)
      else { return this.$message.error(msg) }
    },
    handleChange () {
      this.getParamsData()
    },
    tabClick () {
      this.getParamsData()
    },
    // 获取动态参数和静态属性函数
    async getParamsData () {
      if (this.selectCategories.length !== 3) {
        this.selectCategories = []
        // 应该把这两个也清空，就让下面的渲染数据也清空了
        this.manyTabData = []
        this.onlyTabData = []
        return
      }
      console.log(this.selectCategories, this.cateId)
      const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
        params: { sel: this.activeName }
      })
      this.process(res)
      res.data.forEach(item => {
        item.attr_vals = item.attr_vals.length === 0 ? [] : item.attr_vals.split(',')
        item.newTagInputVisible = false
        item.newTagValue = ''
      })
      this.activeName === 'many' ? this.manyTabData = res.data : this.onlyTabData = res.data
    },
    addDialogDefine () {
      this.$refs.addFormRef.validate(async valid => {
        if (!valid) return
        else {
          const { data: res } = await this.$http.post(`categories/${this.cateId}/attributes`, {
            ...this.addForm,
            attr_sel: this.activeName
          })
          this.process(res)
          this.getParamsData()
          this.addDialogVisible = false
        }
      })
    },
    // 对话框关闭事件
    addDialogClose () {
      // 只要对话框关闭就清空表单  所以我之前没有做好 之前只是点下确认按钮才清空
      this.$refs.addFormRef.resetFields()
    },
    editParamsDataButton (row) {
      this.editAttrId = row.attr_id
      this.editForm.attr_name = row.attr_name
      this.editDialogVisible = true
    },
    editParamsDataDefine () {
      this.$refs.editFormRef.validate(async valid => {
        if (!valid) return
        const { data: res } = await this.$http.put(`categories/${this.cateId}/attributes/${this.editAttrId}`, {
          attr_name: this.editForm.attr_name,
          attr_sel: this.activeName
        })
        this.process(res)
        this.getParamsData()
        this.editDialogVisible = false
      })
    },
    async deleteParamsDataButton (row) {
      const { data: res } = await this.$http.delete(`categories/${this.cateId}/attributes/${row.attr_id}`)
      this.process(res)
      this.getParamsData()
    },
    showNewTagInput (row) {
      row.newTagInputVisible = true
      // 让输入框获得焦点  这是el官网使用的方法 $nextTick
      // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。当页面上的元素被重新渲染后，才执行回调函数
      //  this.$refs.saveTagInput.$refs.input.focus();就是现获取原生的input，然后使用focus()获得焦点
      // 如果直接this.$refs.saveTagInput.focus() 会报错
      // this.$nextTick(_ => {
      //   this.$refs.saveTagInput.$refs.input.focus()
      // })

      // 这里直接使用this.$refs.newTagInputRef.$refs.input.focus()也会报错 必须使用this.$nextTick包裹
      // 但是具体为什么还不知道  一些想法： 因为我们隐藏了tag，显示了input，所以我们已经改变了DOM，如果我们直接
      // 要求获得焦点，但是这个元素还没有被渲染出来，获得焦点就会报错，所以我们使用这个方法，当元素渲染出来后再操作
      this.$nextTick(_ => {
        this.$refs.newTagInputRef.$refs.input.focus()
      })
    },
    async newTagInputBlur (row) {
      if (row.newTagValue.trim().length !== 0) {
        row.attr_vals.push(row.newTagValue)
        this.saveParams(row)
      }
      row.newTagValue = ''
      row.newTagInputVisible = false
    },
    async tagClose (row, index) {
      row.attr_vals.splice(index, 1)
      this.saveParams(row)
    },
    async saveParams (row) {
      const { data: res } = await this.$http.put(`categories/${row.cat_id}/attributes/${row.attr_id}`, {
        attr_name: row.attr_name,
        attr_sel: row.attr_sel,
        attr_vals: row.attr_vals.join(',')
      })
      this.process(res)
    }
  },
  computed: {
    cateId () {
      if (this.selectCategories.length === 3) {
        return this.selectCategories[2]
      } else return null
    },
    titleText () {
      return this.activeName === 'many' ? '动态参数' : '静态属性'
    }
  }
}
</script>

<style lang = "less" scoped>
  .el-card {
    margin-top: 20px;
  }

  .el-table {
    margin-top: 20px;
  }

  .el-tag {
    margin: 5px;
  }

  .input-new-tag {
    width: 15%;
  }
</style>
